package com.asen.commons.core.jdbc.builder.mysql;

import com.asen.commons.core.jdbc.builder.SqlBuilder;
import com.asen.commons.core.jdbc.builder.mysql.filter.FilterParser;
import com.asen.commons.core.jdbc.builder.mysql.filter.FilterParserHolder;
import com.asen.commons.core.jdbc.param.ParamStatementSetter;
import com.asen.commons.core.jdbc.param.SqlColumn;
import com.asen.commons.core.jdbc.param.SqlContext;
import com.asen.commons.core.jdbc.param.SqlContextManager;
import com.asen.commons.core.meta.dao.Condition;
import com.asen.commons.core.meta.dao.FilterGroup;
import com.asen.commons.core.meta.dao.FilterItem;
import com.asen.commons.core.meta.enums.FilterRelationEnum;
import com.asen.commons.utils.BaseAssert;
import com.asen.commons.utils.CollectionUtils;
import com.asen.commons.utils.StringUtils;

import java.util.List;

/**
 * 条件SQL构建器
 *
 * @author Gary
 * @version 1.0
 * @date 2018-11-28
 */
public class WhereBuilder implements SqlBuilder {

    private StringBuilder whereSql = new StringBuilder();

    private SqlContext context;

    private SqlContextManager contextManager;

    private boolean buildFlag = false;

    public WhereBuilder(SqlContext context) {
        this.context = context;
        this.contextManager = SqlContextManager.newInstance(context);
    }

    @Override
    public String getSql() {
        BaseAssert.check(buildFlag, "尚未进行SQL构建，不能执行此操作！");
        return whereSql.toString();
    }

    @Override
    public ParamStatementSetter getParams() {
        return context.getParamSetter();
    }

    public void build(Object model, String... whereFields) throws Exception {
        buildFlag = true;

        if (whereFields == null) {
            return;
        }

        for (String fullName : whereFields) {
            SqlColumn sqlColumn = contextManager.getSqlColumn(fullName);
            if (sqlColumn == null) {
                continue;
            }

            if (whereSql.length() > 0) {
                whereSql.append(" AND ");
            }

            Object value = sqlColumn.getValue(model);
            if (value == null) {
                whereSql.append(sqlColumn.getFullColumn());
                whereSql.append(" = null");
            } else {
                whereSql.append(sqlColumn.getFullColumn());
                whereSql.append(" = ?");
                getParams().setParam(sqlColumn.getJavaType(), value);
            }
        }
    }

    public void build(Condition condition) throws Exception {
        buildFlag = true;

        String sql1 = buildByGroup(condition.getFilterGroups(), condition.getFilterRelation());
        String sql2 = buildByFilter(condition.getFilterItems(), condition.getFilterRelation());

        if (StringUtils.isNotEmpty(sql1)) {
            whereSql.append(sql1);
        }

        if (StringUtils.isNotEmpty(sql2)) {
            if (whereSql.length() > 0) {
                whereSql.append(" ");
                whereSql.append(condition.getFilterRelation());
                whereSql.append(" ");
            }
            whereSql.append(sql2);
        }
    }

    private String buildByGroup(List<FilterGroup> list, FilterRelationEnum relationEnum) throws Exception {
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }

        StringBuilder sql = new StringBuilder();
        for (FilterGroup group : list) {
            StringBuilder sb = new StringBuilder();

            String s1 = buildByGroup(group.getFilterGroups(), group.getFilterRelation());
            String s2 = buildByFilter(group.getFilterItems(), group.getFilterRelation());

            if (StringUtils.isNotEmpty(s1)) {
                sb.append(s1);
            }

            if (StringUtils.isNotEmpty(s2)) {
                if (sb.length() > 0) {
                    sb.append(" ");
                    sb.append(group.getFilterRelation().getDesc());
                    sb.append(" ");
                }
                sb.append(s2);
            }

            if (sb.length() > 0) {
                if (sql.length() > 0) {
                    sql.append(" ");
                    sql.append(relationEnum.getDesc());
                    sql.append(" ");
                }

                sql.append(" (");
                sql.append(sb);
                sql.append(") ");
            }
        }

        if (sql.length() > 0) {
            return sql.toString();
        }

        return null;
    }

    private String buildByFilter(List<FilterItem> list, FilterRelationEnum relationEnum) throws Exception {
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }

        StringBuilder sql = new StringBuilder();
        for (FilterItem filterItem : list) {
            FilterParser filterParser = FilterParserHolder.get(filterItem.getSymbol());
            CharSequence s = filterParser.parse(contextManager, filterItem);
            if (StringUtils.isNotBlank(s)) {
                if (sql.length() > 0) {
                    sql.append(relationEnum.getDesc());
                }
                sql.append(s);
            }
        }

        if (sql.length() > 0) {
            return sql.toString();
        }

        return null;
    }

}
